#define DEBUG
#include <cstdio>
#include <cmath>

using namespace std;

typedef long long ll;
const int maxn=100000, inf=0x7fffffff;

int min(int a, int b) {
  return a<b ? a : b;
}

int max(int a, int b) {
  return a>b ? a : b;
}

class SegmentTree {
public:
  ll sum[4*maxn+1], minv[4*maxn+1], maxv[4*maxn+1], mark[4*maxn+1];

  void markDown(int o, int l, int r) {
    if (mark[o]) {
      sum[o] += (ll)(r-l+1)*mark[o];
      minv[o] += mark[o], maxv[o]+=mark[o];
      if (l!=r) mark[o*2] += mark[o], mark[o*2+1] += mark[o];
      mark[o] = 0;
    }
  }

  void update(int o) {
    sum[o] = sum[o*2]+sum[o*2+1];
    minv[o] = min(minv[o*2], minv[o*2+1]);
    maxv[o] = max(maxv[o*2], maxv[o*2+1]);
  }

  void init(int o, int l, int r, int a[]) {
    if (l==r) sum[o] = minv[o] = maxv[o] = a[l];
    else {
      int mid=(l+r)/2;
      init(o*2, l, mid, a), init(o*2+1, mid+1, r, a);
      update(o);
    }
  }

  void add(int o, int l, int r, int tl, int tr, int tv) {
    markDown(o, l, r);
    if (l==tl && r==tr) {
      mark[o] += tv;
      markDown(o, l, r);
    } else {
      int mid=(l+r)/2;
      if (tl<=mid) add(o*2, l, mid, tl, min(tr, mid), tv);
      else markDown(o*2, l, mid);
      if (tr>mid) add(o*2+1, mid+1, r, max(tl, mid+1), tr, tv);
      else markDown(o*2+1, mid+1, r);
      update(o);
    }
  }

  void div(int o, int l, int r, int tl, int tr, int tv) {
    markDown(o, l, r);
    if (l==tl && r==tr && floor((double)maxv[o]/tv)-maxv[o]==floor((double)minv[o]/tv)-minv[o]) {
      mark[o] += floor((double)minv[o]/tv)-minv[o];
      markDown(o, l, r);
    } else {
      int mid=(l+r)/2;
      if (tl<=mid) div(o*2, l, mid, tl, min(tr, mid), tv);
      else markDown(o*2, l, mid);
      if (tr>mid) div(o*2+1, mid+1, r, max(tl, mid+1), tr, tv);
      else markDown(o*2+1, mid+1, r);
      update(o);
    }
  }

  ll getSum(int o, int l, int r, int tl, int tr) {
    markDown(o, l, r);
    if (l==tl && r==tr) return sum[o];
    else {
      int mid=(l+r)/2;
      ll ret=0;
      if (tl<=mid) ret += getSum(o*2, l, mid, tl, min(tr, mid));
      if (tr>mid) ret += getSum(o*2+1, mid+1, r, max(tl, mid+1), tr);
      return ret;
    }
  }

  int getMin(int o, int l, int r, int tl, int tr) {
    markDown(o, l, r);
    if (l==tl && r==tr) return minv[o];
    else {
      int mid=(l+r)/2, ret=inf;
      if (tl<=mid) ret = min(ret, getMin(o*2, l, mid, tl, min(tr, mid)));
      if (tr>mid) ret = min(ret, getMin(o*2+1, mid+1, r, max(tl, mid+1), tr));
      return ret;
    }
  }
};

int main() {
  freopen("milk.in", "r", stdin);
  freopen("milk.out", "w", stdout);

  static int a[maxn+1];
  int n, q;
  scanf("%d %d", &n, &q);
  for (int i=1; i<=n; i++) scanf("%d", a+i);

  static SegmentTree sgt;
  sgt.init(1, 1, n, a);
  for (int i=1; i<=q; i++) {
    int opt, l, r, x;
    scanf("%d %d %d", &opt, &l, &r);
    if (opt==1) {
      scanf("%d", &x);
      sgt.add(1, 1, n, l, r, x);
    } else if (opt==2) {
      scanf("%d", &x);
      sgt.div(1, 1, n, l, r, x);
    } else if (opt==3) printf("%d\n", sgt.getMin(1, 1, n, l, r));
    else printf("%lld\n", sgt.getSum(1, 1, n, l, r));
  }

  fclose(stdin);
  fclose(stdout);
  return 0;
}
